<template>
  <div>
    <el-button class="zf-record" :type="recording ? '' : 'primary'" :icon="recording? 'el-icon-loading' : 'el-icon-service'" circle @click="recBtnClick"></el-button>
    <web-sock url="http://" ref="websock" v-on:onmessage="onmessage"></web-sock>
  </div>
</template>

<script>
  import WebSock from "./WebSock.vue";
  export default {
    name: 'Recorder',
    components: {
      WebSock
    },
    data () {
      return {
        recording:false
      }
    },
    methods:{
      onmessage(data){
        console.debug('onmessage!!!!!!!!!!!!!!')
        this.$emit("onmessage", data)
      },
      recBtnClick(){
        if (this.recording){
          this.stopRec()
        }else{
          this.startRec()
        }
        this.recording = !this.recording
        console.debug('after click:', this.recording)
      },
      startRec(){
        const constraints = {
          video: false,
          audio: {
            channelCount: 1,
            sampleRate:8000,
            sampleSize:16,
            echoCancellation: false
          },
          channelCount: 1,
          sampleRate:8000,
          sampleSize:16,
          echoCancellation: false
        }
        navigator.mediaDevices
          .getUserMedia(constraints)
          .then(this._micCaptured.bind(this))
          .catch(this._micError.bind(this))
      },
      stopRec () {
        console.debug('停了')
        this.stream.getTracks().forEach((track) => track.stop())
        this.input.disconnect()
        this.processor.disconnect()
        this.context.close()
        this.$refs.websock.close()
      },
      _micCaptured (stream) {
        this.context    = new(window.AudioContext || window.webkitAudioContext)({
          latencyHint: "playback",
          sampleRate: 8000
        })
        // this.context.sampleRate = 8000
        console.debug("audioContext.sampleRate1:", this.context.sampleRate);
        this.input      = this.context.createMediaStreamSource(stream)
        this.processor  = this.context.createScriptProcessor(this.bufferSize, 1, 1)
        this.stream     = stream
        this.processor.onaudioprocess = (ev) => {
          const sample = ev.inputBuffer.getChannelData(0)


          let result = this.encode(sample)
          console.debug(result)
          this.$refs.websock.send(result)

        }
        this.input.connect(this.processor)
        this.processor.connect(this.context.destination)
      },
      _micError (error) {

      },
      encode(arrayBuffer){
        const data = new Float32Array(arrayBuffer)
        const data2 = this._downsampleBuffer(data, 44100, 8000)
        const out = new Int16Array(data2.length)
        const out2 =new Uint8Array(out.length * 2) ;
        this._floatTo16BitPCM(data2, out)
        for (let i =0; i < out.length; i++){
          let s = out[i]
          let a = (s & 0xff00) >> 8
          let b = (s & 0x00FF)
          out2[i*2] = b
          out2[i*2 + 1] = a
        }
        return out2
      },
      _floatTo16BitPCM(input, output) {
        for (let i = 0; i < input.length; i++) {
          const s = Math.max(-1, Math.min(1, input[i]))
          output[i] = (s < 0 ? s * 0x8000 : s * 0x7FFF)
        }
      },
      _downsampleBuffer(buffer, origrate, rate) {
        if (rate == origrate) {
          return buffer;
        }
        if (rate > origrate) {
          throw "downsampling rate show be smaller than original sample rate";
        }

        let sampleRateRatio = origrate / rate; //计算压缩率，注意这里要取整数
        let newLength = Math.round(buffer.length / sampleRateRatio);
        let result = new Float32Array(newLength);
        let offsetResult = 0;
        let offsetBuffer = 0;
        while (offsetResult < result.length) {
          let nextOffsetBuffer = Math.round((offsetResult + 1) * sampleRateRatio);
          let accum = 0,
            count = 0;
          for (let i = offsetBuffer; i < nextOffsetBuffer && i < buffer.length; i++) {
            accum += buffer[i];
            count++;
          }
          result[offsetResult] = accum / count;
          offsetResult++;
          offsetBuffer = nextOffsetBuffer;
        }
        return result;
      }


    },
    mounted(){
      this.$refs.websock.init()
    }
  }
</script>


<style scoped>
  .zf-record{
    font-size:90px;
    padding:20px
  }

  .zf-reglist{
    margin-top: 100px;
    font-size: large;
  }
</style>
